/*******************************************************************************
 *                                    ZLG
 *                         ----------------------------
 *                         innovating embedded platform
 *
 * Copyright (c) 2001-present Guangzhou ZHIYUAN Electronics Co., Ltd.
 * All rights reserved.
 *
 * Contact information:
 * web site:    https://www.zlg.cn
 *******************************************************************************/
#ifndef __HPM6E00_UART_H__
#define __HPM6E00_UART_H__

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus*/
#include "core/include/hpm6e00_clk.h"
#include "core/include/hpm6e00_regs_uart.h"
#include "common/hpm_common.h"
#include "common/hpm_errno.h"
#include <stdint.h>
#include <stdio.h>

/* \brief 最小波特率*/
#define HPM_UART_MINIMUM_BAUDRATE   (200U)
/* \brief 串口重试次数*/
#define HPM_UART_DRV_RETRY_COUNT    (5000U)

#ifndef HPM_UART_BAUDRATE_TOLERANCE
#define HPM_UART_BAUDRATE_TOLERANCE (3)
#endif

/* \brief 过采样率最大值*/
#define HPM_UART_OSC_MAX            (32U)
/* \brief 过采样率最小值*/
#define HPM_UART_OSC_MIN            (8U)

/* \brief 波特率分频最大值*/
#define HPM_UART_BAUDRATE_DIV_MAX   (0xFFFFU)
/* \brief 波特率分频最小值*/
#define HPM_UART_BAUDRATE_DIV_MIN   (1U)

/* \brief 设置分频低 8 位*/
#define UART_DLL_DLL_SET(x)    (((uint32_t)(x) << UART_DLL_DLL_POS) & UART_DLL_DLL_MASK)
/* \brief 获取分频低 8 位*/
#define UART_DLL_DLL_GET(x)    (((uint32_t)READ_REG32(x) & UART_DLL_DLL_MASK) >> UART_DLL_DLL_POS)
/* \brief 设置分频高 8 位*/
#define UART_DLM_DLM_SET(x)    (((uint32_t)(x) << UART_DLM_DLM_POS) & UART_DLM_DLM_MASK)
/* \brief 获取分频高 8 位*/
#define UART_DLM_DLM_GET(x)    (((uint32_t)READ_REG32(x) & UART_DLM_DLM_MASK) >> UART_DLM_DLM_POS)
/* \brief 设置过采样率*/
#define UART_OSCR_OSC_SET(x)   (((uint32_t)(x) << UART_OSCR_OSC_POS) & UART_OSCR_OSC_MASK)
/* \brief 获取过采样率*/
#define UART_OSCR_OSC_GET(x)   (((uint32_t)READ_REG32(x) & UART_OSCR_OSC_MASK) >> UART_OSCR_OSC_POS)

#define UART_THR_THR_SET(x)    (((uint32_t)(x) << UART_THR_THR_POS) & UART_THR_THR_MASK)
#define UART_THR_THR_GET(x)    (((uint32_t)READ_REG32(x) & UART_THR_THR_MASK) >> UART_THR_THR_POS)

#define UART_MCR_LOOP_SET(x)   (((uint32_t)(x) << UART_MCR_LOOP_POS) & UART_MCR_LOOP_MASK)
#define UART_MCR_LOOP_GET(x)   (((uint32_t)READ_REG32(x) & UART_MCR_LOOP_MASK) >> UART_MCR_LOOP_POS)

#define UART_MCR_AFE_SET(x)    (((uint32_t)(x) << UART_MCR_AFE_POS) & UART_MCR_AFE_MASK)
#define UART_MCR_AFE_GET(x)    (((uint32_t)READ_REG32(x) & UART_MCR_AFE_MASK) >> UART_MCR_AFE_POS)

#define UART_MCR_RTS_SET(x)    (((uint32_t)(x) << UART_MCR_RTS_POS) & UART_MCR_RTS_MASK)
#define UART_MCR_RTS_GET(x)    (((uint32_t)READ_REG32(x) & UART_MCR_RTS_MASK) >> UART_MCR_RTS_POS)

#define UART_IDLE_CFG_RX_IDLE_EN_SET(x)   (((uint32_t)(x) << UART_IDLE_CFG_RX_IDLE_EN_POS) & UART_IDLE_CFG_RX_IDLE_EN_MASK)
#define UART_IDLE_CFG_RX_IDLE_EN_GET(x)   (((uint32_t)(x) & UART_IDLE_CFG_RX_IDLE_EN_MASK) >> UART_IDLE_CFG_RX_IDLE_EN_POS)

#define UART_IDLE_CFG_RX_IDLE_THR_SET(x)  (((uint32_t)(x) << UART_IDLE_CFG_RX_IDLE_THR_POS) & UART_IDLE_CFG_RX_IDLE_THR_MASK)
#define UART_IDLE_CFG_RX_IDLE_THR_GET(x)  (((uint32_t)(x) & UART_IDLE_CFG_RX_IDLE_THR_MASK) >> UART_IDLE_CFG_RX_IDLE_THR_POS)

#define UART_IDLE_CFG_RX_IDLE_COND_SET(x) (((uint32_t)(x) << UART_IDLE_CFG_RX_IDLE_COND_POS) & UART_IDLE_CFG_RX_IDLE_COND_MASK)
#define UART_IDLE_CFG_RX_IDLE_COND_GET(x) (((uint32_t)(x) & UART_IDLE_CFG_RX_IDLE_COND_MASK) >> UART_IDLE_CFG_RX_IDLE_COND_POS)

/* \brief 串口校验 */
typedef enum parity {
    parity_none = 0,
    parity_odd,
    parity_even,
    parity_always_1,
    parity_always_0,
} uart_parity_t;

/* \brief 串口停止位 */
typedef enum num_of_stop_bits {
    stop_bits_1 = 0,
    stop_bits_1_5,
    stop_bits_2,
} uart_stop_bits_t;

/* \brief 串口 FIFO 触发等级 */
typedef enum uart_fifo_trg_lvl {
    uart_rx_fifo_trg_not_empty         = 0,
    uart_rx_fifo_trg_gt_one_quarter    = 1,
    uart_rx_fifo_trg_gt_half           = 2,
    uart_rx_fifo_trg_gt_three_quarters = 3,

    uart_tx_fifo_trg_not_full          = 0,
    uart_tx_fifo_trg_lt_three_quarters = 1,
    uart_tx_fifo_trg_lt_half           = 2,
    uart_tx_fifo_trg_lt_one_quarter    = 3,
} uart_fifo_trg_lvl_t;

/* \brief 串口中断 ID */
typedef enum uart_intr_id {
    uart_intr_id_modem_stat    = 0x0,
    uart_intr_id_tx_slot_avail = 0x2,
    uart_intr_id_rx_data_avail = 0x4,
    uart_intr_id_rx_line_stat  = 0x6,
    uart_intr_id_rx_timeout    = 0xc,
} uart_intr_id_t;

/* \brief 数据长度 */
typedef enum word_length {
    word_length_5_bits = 0,
    word_length_6_bits,
    word_length_7_bits,
    word_length_8_bits,
} word_length_t;

typedef enum uart_rxline_idle_cond {
    uart_rxline_idle_cond_rxline_logic_one = 0,         /**< Treat as idle if the RX Line high duration exceeds threshold */
    uart_rxline_idle_cond_state_machine_idle = 1        /**< Treat as idle if the RX state machine idle state duration exceeds threshold */
} uart_rxline_idle_cond_t;

/* \brief 串口 Modem 配置结构体 */
struct uart_modem_cfg {
    bool_t auto_flow_ctrl_en;     /**< Auto flow control enable flag */
    bool_t loop_back_en;          /**< Loop back enable flag */
    bool_t set_rts_high;          /**< Set signal RTS level high flag */
};

struct uart_rxline_idle_cfg {
    bool_t                  detect_enable;         /**< RX Line Idle detection flag */
    bool_t                  detect_irq_enable;     /**< Enable RX Line Idle detection interrupt */
    uart_rxline_idle_cond_t idle_cond;             /**< RX Line Idle detection condition */
    uint8_t                 threshold;             /**< UART RX Line Idle detection threshold, in terms of bits */
};

/* \brief 串口配置结构体 */
struct hpm_uart_cfg {
    uint32_t                   src_freq_in_hz;             /* 串口时钟频率（赫兹）*/
    uint32_t                    baudrate;                   /* 波特率 */
    uint8_t                     num_of_stop_bits;           /* 停止位 */
    uint8_t                     word_length;                /* 数据长度 */
    uint8_t                     parity;                     /* 校验 */
    uint8_t                     tx_fifo_level;              /* 发送 FIFO 级别 */
    uint8_t                     rx_fifo_level;              /* 接收 FIFO 级别 */
    bool_t                      dma_enable;                 /* DMA 使能位 */
    bool_t                      fifo_enable;                /* FIFO 使能位 */
    struct uart_modem_cfg       modem_cfg;                  /* Modem 配置 */
    struct uart_rxline_idle_cfg rxidle_cfg;                 /* 接收空闲配置 */
};

/**
 * \brief 串口默认配置设置
 *
 * \param[in] p_cfg 配置结构体
 */
void uart_cfg_default_set(struct hpm_uart_cfg *p_cfg);
/**
 * \brief 串口初始化
 *
 * \param[in] p_uart_reg 相关串口寄存器
 * \param[in] p_cfg      配置结构体
 *
 * \retval 成功返回 0
 */
int uart_init(hpm_uart_reg_t *p_uart_reg, struct hpm_uart_cfg *p_cfg);
/**
 * \brief 串口反初始化
 *
 * \param[in] p_uart_reg 相关串口寄存器
 */
void uart_deinit(hpm_uart_reg_t *p_uart_reg);
/**
 * \brief 获取串口中断 ID
 *
 * \param[in] p_uart_reg 相关串口寄存器
 *
 * \retval 成功返回串口中断 ID
 */
uint32_t uart_irq_id_get(hpm_uart_reg_t *p_uart_reg);
/**
 * \brief 串口中断设置
 *
 * \param[in] p_uart_reg 相关串口寄存器
 * \param[in] mask       中断屏蔽位
 * \param[in] is_enable  是否使能
 *
 * \retval 成功返回 0
 */
int uart_int_set(hpm_uart_reg_t *p_uart_reg, uint32_t mask, uint8_t is_enable);
/**
 * \brief 串口接收空闲检测初始化
 *
 * \param[in] p_uart_reg   相关串口寄存器
 * \param[in] p_rxidle_cfg 接收空闲配置结构体
 *
 * \retval 成功返回 0
 */
int uart_init_rxline_idle_detection(hpm_uart_reg_t              *p_uart_reg,
                                    struct uart_rxline_idle_cfg *p_rxidle_cfg);
/**
 * \brief 串口字节发送
 *
 * \param[in] p_uart_reg 相关串口寄存器
 * \param[in] c          要发送的字节
 *
 * \retval 成功返回 1
 */
int uart_byte_send(hpm_uart_reg_t *p_uart_reg, uint8_t c);
/**
 * \brief 串口字节接收
 *
 * \param[in] p_uart_reg 相关串口寄存器
 * \param[in] p_c        字节缓存
 *
 * \retval 成功返回 1
 */
int uart_byte_receive(hpm_uart_reg_t *p_uart_reg, uint8_t *p_c);
#ifdef __cplusplus
}
#endif  /* __cplusplus  */
#endif

